﻿using System;
using UnityEngine;

namespace Z1029.PhiPlayer.OpenSource
{
    public sealed class Hold : Note
    {
        bool isHolding;
        bool missHold;
        public GameObject holdHead;
        float holdEffectTimer;
        bool missedNote;
        HitACC holdFirstHit;

        bool isJudged;

        public override void OnNoteStart()
        {
            type = NoteType.Hold;
            holdFirstHit = HitACC.Miss;
            isHolding = false;
            isJudged = false;
            missedNote = false;
        }

        public void UpdateHoldSize()
        {
            float sizeY;
            sizeY = Mathf.Abs(
                (
                judgeline.GetSpeedDistance(noteData.time + noteData.holdTime) -
                    judgeline.GetSpeedDistance(noteData.time)
                    )
                    * noteData.speed);
            if (judgeline.GetSpeedDistance(noteData.time) <= 0)
            {
                sizeY = Mathf.Abs(
                    judgeline.GetSpeedDistance(
                        noteData.time + noteData.holdTime)
                        )
                    * noteData.speed;
            }
            if (sizeY != 0) holdHead.transform.localScale = new Vector3(1, 3 / sizeY, 1);
            sizeY /= 19f;
            transform.localScale = new Vector3(LevelController.noteSize + LevelController.instance.noteSizeOffset, sizeY, 1f);
        }

        public void SetDirection()
        {
            if (direction == Direction.Below)
            {
                Vector3 localEulerAngles = new Vector3(0f, 0f, -180f);
                transform.localEulerAngles = localEulerAngles;
            }
        }

        public void UpdateHoldJudge()
        {
            if (InJudgeTime(noteData.time) && !isJudged)
            {
                AddToNearJudgeNotes();
            }
            if (LevelController.nowTime - 0.18f > noteData.time && !isHolding)
            {
                //MissHold();
            }
            if (LevelController.nowTime > noteData.time)
            {
                holdHead.SetActive(false);
                transform.localPosition = new Vector3(noteData.positionX, 0f, 0f);
                holdEffectTimer += Time.deltaTime;
                if (isHolding && holdEffectTimer > (60 / judgeline.bpm) / 2 && !missHold)
                {
                    OnHold(holdFirstHit);
                    holdEffectTimer = 0f;
                }
                if (LevelController.nowTime - noteData.time > noteData.holdTime)
                {
                    Hit(holdFirstHit);
                }
            }
        }

        public void SetHoldPosition()
        {
            if (judgeline.GetSpeedDistance(noteData.time) >= 0) transform.localPosition = new Vector3(noteData.positionX, CalculateNotePosY(), 0f);
            //if (judgeline.GetSpeedDistance(noteData.time) > 0) transform.localPosition = new Vector3(noteData.positionX, (float)(noteData.time-LevelController.nowTime)*noteData.speed, 0f);
        }

        /*public override float CalculateDistance()
        {
            float d=base.CalculateDistance();
            d /= noteData.speed;
            d *= speed;
            return d;
        }*/

        public override void Update()
        {
            UpdateHoldSize();
            SetDirection();
            UpdateHoldJudge();
            SetHoldPosition();
            //UpdateHoldNoteSpeed();
            ///Auto
            if (LevelController.nowTime > noteData.time && !isHolding) OnClick();
        }

        public void OnClick()
        {
            if (!missHold)
            {
                holdFirstHit = HitACC.Perfect;
            }
            isJudged = true;
            RemoveNearJudgeNotes();
            OnHold(holdFirstHit);
            LevelController.instance.hitEffectManager.PlayHitSoundById(1);
            isHolding = true;
        }

        public void MissHold()
        {
            if (!missedNote)
            {
                MissNote();
                missedNote = true;
            }
            thisRenderer.color = new Color(1f, 1f, 1f, 0.4f);
            holdFirstHit = HitACC.Miss;
            isJudged = true;
            missHold = true;
            isHolding = false;
        }

        public void OnHold(HitACC acc)
        {
            LevelController.instance.hitEffectManager.ShowEffect(acc, transform.position, judgeline.transform, 0, NoteType.Hold);
            if (acc == HitACC.Miss)
            {
                thisRenderer.color = new Color(1f, 1f, 1f, 0.6f);
                missHold = true;
                isJudged = true;
            }
        }

        public static bool InJudgeTime(double time)
        {
            bool flag = Mathf.Abs((float)(LevelController.nowTime - time)) < 0.135f;
            return flag;
        }
    }
}